# -*- coding: utf-8 -*-
import hashlib
import json
import time

import requests
from django.conf import settings

from async import async_job
from common.cache import redis_cache
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError

_LOGGER = track_logging.getLogger(__name__)

_APPID = '1002242'
_API_KEY = '3f8463bcff9047c49104d8cc910652c6'

_GATEWAY_INFO = {'gateway': "https://api.dq.cn/pay/KDBank.aspx", 'update_timestamp': 0}

APP_CONF = {
    '1002242': {
        'API_KEY': '3f8463bcff9047c49104d8cc910652c6',
    }
}


def _get_api_key(mch_id):
    return APP_CONF[mch_id]['API_KEY']


def _gen_key(s):
    m = hashlib.md5()
    m.update(s.encode('gb2312'))
    sign = m.hexdigest().lower()
    return sign


def _get_server_timestamp():
    response = requests.get('https://api.dq.cn/GetTimesTamp.aspx')
    if response.status_code == 200:
        return response.text
    else:
        return ''


def _gen_get_gateway_sign(d):
    s = d['P_UserId'] + '|' + d['P_ServiceName'] + '|' + d['P_TimesTamp'] + '|' + _API_KEY
    return _gen_key(s)


def _get_gateway():
    past_time = time.time() - _GATEWAY_INFO['update_timestamp']
    if past_time > 3600 * 24:
        # if past_time > 0:
        d = {}
        d['P_UserId'] = _APPID
        d['P_ServiceName'] = 'GetBankGateway'
        d['P_TimesTamp'] = _get_server_timestamp()
        d['P_PostKey'] = _gen_get_gateway_sign(d)

        s = 'https://api.dq.cn/pay/KDSubmitUrl.aspx?P_UserId={}&P_ServiceName={}&P_TimesTamp={}&P_PostKey={}'.format(
            d['P_UserId'],
            d['P_ServiceName'],
            d['P_TimesTamp'],
            d['P_PostKey'],
        )
        response = requests.get(s)
        _LOGGER.info("gateway : " + response.text)
        r = json.loads(response.text)
        _GATEWAY_INFO['gateway'] = r['P_SubmitUrl']
        _GATEWAY_INFO['update_timestamp'] = time.time()
    return _GATEWAY_INFO['gateway']


# $P_PostKey = md5($P_UserId.'|'.$P_OrderId.'|'.$P_CardId.'|'.$P_CardPass .'|'.$P_FaceValue.'|'.$P_ChannelId.'|'.$SalStr);
def generate_order_create_sign(d, key):
    s = d['P_UserId'] + '|' + d['P_OrderId'] + '|' + '|' + '|' + d['P_FaceValue'] + '|' + d['P_ChannelId'] + '|' + key
    return _gen_key(s)


def create_charge(pay, pay_amount, info):
    ''' 创建订单 '''
    app_id = info['app_id']
    api_key = _get_api_key(app_id)
    service = info.get('service')
    # bank_type = 36 if service == 'alipay' else 33
    if service == 'alipay':
        bank_type = 36
    elif service == 'wxpay':
        bank_type = 33
    else:
        bank_type = 92  # qq
    d = {}
    d['P_UserId'] = app_id
    d['P_OrderId'] = str(pay.id)
    d['P_FaceValue'] = str(pay_amount)
    d['P_ChannelId'] = str(bank_type)
    d['P_Price'] = str(pay_amount)
    d['P_Quantity'] = 1
    d['P_Result_URL'] = '{}/pay/api/third/notify/kdpay/{}'.format(settings.NOTIFY_PREFIX, app_id)
    _LOGGER.info(d)
    d['P_PostKey'] = generate_order_create_sign(d, api_key)

    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    response = requests.post(_get_gateway(), data=d, headers=headers, timeout=3)
    _LOGGER.info("kdpay create charge data: %s %s",
                 response.status_code, response.text)

    cache_id = redis_cache.save_html(pay.id, response.text)
    charge_resp = {
        'charge_info': settings.PAY_CACHE_URL + cache_id,
    }
    return charge_resp


# P_PostKey=md5(P_UserId|P_OrderId|P_CardId|P_CardPass|P_FaceValue|P_ChannelId|P_PayMoney|P_ErrCode|SalfStr)
def generate_notify_sign(params, key):
    s = params[u'P_UserId'] + '|' \
        + params[u'P_OrderId'] + '|' \
        + params[u'P_CardId'] + '|' \
        + params[u'P_CardPass'] + '|' \
        + params[u'P_FaceValue'] + '|' \
        + params[u'P_ChannelId'] + '|' \
        + params[u'P_PayMoney'] + '|' \
        + params[u'P_ErrCode'] + '|' \
        + key

    return _gen_key(s)


def verify_notify_sign(params, key):
    sign = params[u'P_PostKey']
    calculated_sign = generate_notify_sign(params, key)
    if sign != calculated_sign:
        _LOGGER.info("kdpay sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % params)


def check_notify_sign(request, app_id):
    data = dict(request.GET.iteritems())
    api_key = _get_api_key(app_id)
    _LOGGER.info("kdpay notify data: %s", data)
    verify_notify_sign(data, api_key)
    pay_id = data[u'P_OrderId']
    if not pay_id:
        _LOGGER.error("fatal error, out_trade_no not exists, data: %s" % data)
        raise ParamError('kdpay event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    mch_id = pay.mch_id
    trade_status = data[u'P_ErrCode']
    trade_no = data[u'P_OrderId']
    total_fee = float(data[u'P_PayMoney'])

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)
    if trade_status == '0':
        _LOGGER.info('kdpay check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        # async notify
        async_job.notify_mch(pay_id)


_QUERY_GATEWAY = 'https://api.dq.cn/pay/query.aspx'


# P_UserId=1002242&P_OrderId=1622610092088099840&P_ChannelId=36&P_CardId=&P_payMoney=2.0000&P_flag=1&P_status=1&P_ErrMsg=支付成功&P_PostKey=f8aee553120d8e1229bcbcd753c137ce&P_KD_OrderNo=&P_KD_OrderTime=
def _get_str(s, start, end):
    p1 = s.index(start)
    p2 = s.index(end, p1 + len(start))
    if p2 > p1:
        return s[p1 + len(start): p2]
    else:
        return ''


def query_charge(pay_order, app_id, service):
    ''' 查询订单 '''
    # prepare param
    s = 'P_UserId={}&P_OrderId={}&P_ChannelId={}&P_CardId=&P_FaceValue={}'.format(
        app_id,
        str(pay_order.id),
        str(36 if service == 'alipay' else 33),
        str(pay_order.total_fee),
    )

    s1 = s + '&P_PostKey=' + _get_api_key(app_id)
    key = _gen_key(s1)
    tmp_url = _QUERY_GATEWAY + '?' + s + '&P_PostKey=' + key
    response = requests.get(tmp_url, timeout=3)
    _LOGGER.info('kdpay query : ' + response.text)
    if response.status_code == 200:

        trade_status = _get_str(response.text, '&P_status=', '&')
        trade_no = _get_str(response.text, '&P_OrderId=', '&')
        total_fee = float(_get_str(response.text, '&P_payMoney=', '&'))
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee
        }

        _LOGGER.info('kdpay query extend: ' + trade_status + ' ' + trade_no + ' ' + total_fee)
        if trade_status == '1':
            _LOGGER.info('kdpay query order success, user_id:%s pay_id:%s' % (pay_order.mch_id, str(pay_order.id)))
            res = order_db.add_pay_success(pay_order.mch_id, pay_order.id,
                                           total_fee, trade_no, extend)
            if res:
                # async notify
                async_job.notify_mch(pay_order.id)
    else:
        _LOGGER.warn('kdpay data error, status_code: %s', response.status_code)
